<?php

namespace mpend\modules\shop\models;

use Yii;
use yii\db\Exception;
use common\models\shop\ShopCart;
use common\models\shop\ShopGoods;
use common\models\shop\ShopOrder;
use common\models\shop\ShopOrderGoods;
use common\helpers\ArrayHelper;
use common\models\user\UserAddress;
use common\models\freight\FreightReceiver;
use common\logics\ExpressCalculator;

/**
 * 用户下单模型
 * 
 * @author emhome<emhome@163.com>
 * @since 2.0
 */
class OrderPlaceForm extends \common\base\Model {

    /**
     * @var integer 下单用户ID
     */
    public $user_id;

    /**
     * @var integer 收件地址
     */
    public $address_id;

    /**
     * @var string 优惠券
     */
    public $coupons;

    /**
     * @var string 购物车中待结算的商品
     */
    public $carts;

    /**
     * @var null 用户收件地址
     */
    private $_address = null;

    /**
     * @var array 购物车数据
     */
    private $_carts = [];

    /**
     * 请求参数校验
     * @inheritdoc
     */
    public function rules() {
        return [
            [['user_id', 'carts', 'address_id'], 'required'],
            ['carts', 'validateCarts'],
            ['address_id', 'validateAddress'],
            ['coupons', 'validateCoupons'],
        ];
    }

    /**
     * 校验购物车中的商品
     * @param string $attribute the attribute currently being validated
     */
    public function validateCarts($attribute) {
        if ($this->hasErrors()) {
            return;
        }
        $cartIds = $this->$attribute;
        if (!empty($cartIds)) {
            $carts = $this->getCartData($cartIds);
            $realCarts = ArrayHelper::getColumn($carts, 'id');
            if (array_diff($realCarts, $cartIds)) {
                $this->addError($attribute, '所购商品状态已发生变化');
            }
        } else {
            $this->addError($attribute, '未提交任何待结算商品信息');
        }
    }

    /**
     * 校验收件地址
     * @param string $attribute the attribute currently being validated
     */
    public function validateAddress($attribute) {
        if ($this->hasErrors()) {
            return;
        }
        if ($this->getAddress() == null) {
            $this->addError($attribute, '未找到当前选择的收件地址信息');
        }
    }

    /**
     * 校验优惠信息
     * @param string $attribute the attribute currently being validated
     */
    public function validateCoupons($attribute) {
        if ($this->hasErrors()) {
            return;
        }
    }

    /**
     * 获取用户收件地址
     * @return UserAddress|null
     */
    protected function getAddress() {
        if ($this->_address === null) {
            $this->_address = UserAddress::find()->where([
                'id' => $this->address_id,
                'user_id' => $this->user_id,
            ])->one();
        }
        return $this->_address;
    }

    /**
     * 设置购物车数据
     * @return \common\models\trade\Partner|null
     */
    protected function setCartData($ids = []) {
        $this->_carts = ShopCart::waitBalance($this->user_id, $ids);
    }

    /**
     * 获取购物车数据
     * @return \common\models\trade\Partner|null
     */
    protected function getCartData($ids = []) {
        if (empty($this->_carts)) {
            $this->setCartData($ids);
        }
        return $this->_carts;
    }

    /**
     * 订单下单保存
     */
    public function save() {
        if (!$this->validate()) {
            return $this->dumpError('下单失败');
        }
        $carts = $this->getCartData();

        $expressItems = [];
        $cartIds = [];
        $goodsAttributes = [];
        $amount = 0;
        $discount = 0;
        foreach ($carts as $cart) {
            $amount += $cart->originalPrice * $cart->num;
            $discount += $cart->discount * $cart->num;
            $expressItems[] = [
                'product_id' => $cart->product_id,
                'num' => $cart->num,
            ];
            $goodsAttributes[] = ArrayHelper::merge($cart->skuAttributes, [
                'product_id' => $cart->product_id,
                'goods_id' => $cart->goods_id,
                'name' => $cart->name,
                'goods_number' => $cart->num,
            ]);
            $cartIds[] = $cart->id;
        }
        //设置订单收件信息
        $address = $this->getAddress();

        //邮费计算
        $calcexpress = new ExpressCalculator();
        $calcexpress->setAttributes([
            'items' => $expressItems,
            'areacode' => $address->area_code,
        ]);
        $express = $calcexpress->reckon();

        $receiver = new FreightReceiver();
        $receiver->attributes = [
            'user_id' => $address->user_id,
            'name' => $address->name,
            'mobile' => $address->mobile,
            'province' => $address->province,
            'city' => $address->city,
            'district' => $address->district,
            'address' => $address->address_detail,
            'area_code' => $address->area_code,
            'postal_code' => $address->postal_code,
            'price' => $express,
            'from' => FreightReceiver::FROM_SHOP,
        ];

        //创建交易
        $order = new ShopOrder();
        $order->attributes = [
            'user_id' => $this->user_id,
            'amount' => $amount + $express,
            'discount' => $discount,
            'express_price' => $express,
            'status' => ShopOrder::STATUS_DEFAULT,
        ];
        $order->generateNo();

        //开启事务
        $transaction = Yii::$app->db->beginTransaction();
        try {
            if (!$receiver->save()) {
                throw new Exception('收件信息保存失败！');
            }
            $order->receiver_id = $receiver->id;
            if (!$order->save()) {
                throw new Exception('交易创建失败！');
            }
            $orderId = $order->id;
            $orderGoods = new ShopOrderGoods();
            foreach ($goodsAttributes as $_attributes) {
                $_model = clone $orderGoods;
                $_model->setAttributes($_attributes);
                $_model->order_id = $orderId;
                if (!$_model->save()) {
                    throw new Exception('交易创建失败！');
                }
                //变更库存
                $_goods = ShopGoods::findOne($_model->goods_id);
                $_goods->stock = $_goods->stock - $_model->goods_number;
                if (!$_goods->save()) {
                    throw new Exception('库存分配失败！');
                }
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->dumpError($e->getMessage());
        }

        if (YII_ENV_PROD) {
            //创建自动过期任务队列
            $taskid = Yii::$app->queue->delay($order->countdown)->push(new \common\jobs\ShopOrderExpiredJob([
                'order_id' => $order->id
            ]));
            Yii::$app->cache->set('queue_shop_order_' . $order->id, $taskid);
        }

        ShopCart::deleteAll(['id' => $cartIds]);

        return [
            'order_id' => $order->id,
            'scope' => 'shop',
        ];
    }

    public function formatList($list) {
        $data = [];
        foreach ($list as $model) {
            $goods = $model->goods;
            if (!$goods) {
                continue;
            }
            $data[$model->goods_id] = [
                'id' => $model->goods_id,
                'product_id' => $goods->product_id,
                'product_name' => $goods->product->name,
                'name' => $goods->name,
                'cover' => $goods->cover ?: $goods->product->cover,
                'code' => $goods->goods_no,
                'price' => $goods->memberPrice,
                'number' => $model->num,
                'discount' => $goods->discount,
                'type_id' => $model->product->type_id,
                'brand_id' => $model->product->brand_id,
                'subtotal' => ($goods->memberPrice - $goods->discount) * $model->num,
            ];
        }
        return $data;
    }

}
